javascript 继承–终极篇

JavaScript 不包含传统的类继承模型,而是使用 prototype 原型模型。所以大家提到的JavaScript的继承其实就是基于原型的继承。

1.继承产生的原因—作用

C++有类的概念,比如说类`动物`,`猫`和`狗`都属于`动物`,有很多的相似性。如果单独构造这两者,效率不高,而如果定义一个基类,通过此基类及个性化设计来实现这两者将会比较高效。

所以继承的作用是让子类可访问父类的属性和方法.且子类也能做父类。

2.继承的简单实现
使用new关键字或者object.create。
两种大方法:
2.1.原型链继承(使用prototype)
我最开始理解的继承应该如下实现:

function ClassA(name){
    this.name = name;
}

ClassA.prototype.sayName = function(){
    alert(this.name);
}

var a1 = new ClassA('a1');
var a2 = new ClassA('a2');
a1.sayName();//a1
a2.sayName();//a2

以上实现确没有子类,扩展如下

function ClassA(){
}

ClassA.prototype.name = 'A';
ClassA.prototype.sayName = function(){
    alert(this.name);
}

var ClassB = new ClassA();
var b1 = new ClassB();// Uncaught TypeError: ClassB is not a constructor
b1.sayName(); 

以上报错:Uncaught TypeError: ClassB is not a constructor
正确写法如下:

function ClassA(){
    this.id =['A'];
}

ClassA.prototype.name = 'A';
ClassA.prototype.sayName = function(){
    alert(this.name);
}

function ClassB(){  
}

ClassB.prototype = new ClassA();
ClassB.prototype.constructor = ClassB;// 不加这句,通过ClassB构造的实例的构造器反而是ClassA.加了这句避免混乱

var b1 = new ClassB();
var b2 = new ClassB();
b1.id.push ('b1');
console.log(b1.id,b2.id);//['A',b1'] ['A',b1']

缺点:
(1).来自原型对象的属性所有实例共享,所以有可能修改实例会修改原型
(2).不能向父类构造函数传参

继承:父类、子类、用子类构造的实例

2.2.类式继承

function ClassA(name){
    this.name = name;
    this.id || (this.id = []);
    this.id.push(name);
    this.sayId = function(){
        alert(this.id);
    };
}

function ClassB(name){
    ClassA.call(this,name);
}

var b1 = new ClassB('b1');
var b2 = new ClassB('b2');
console.log(b1.id);//["b1"]
console.log(b2.id);//["b2"]

完全复制了父类的属性到子类上。
缺点:
(1).每个子类实例都持有新的sayId函数,占用内存,影响性能。

3.继承的实际使用
以上两种方法是原理方法,但是各有优缺点。基于这两种原理,又产生了一些有效的方法

3.1.组合继承(最常用)

function ClassA(name){
    this.id = [name];
}

ClassA.prototype.sayId = function(){
    console.log(this.id);
}

function ClassB(name){
    ClassA.call(this,name);//复制一份属性出来
}
ClassB.prototype = new ClassA();

var b1 = new ClassB('B1');
var b2 = new ClassB('B2');
b1.id.push('b1');
b2.id.push('b2');
console.log(b1.id,b2.id);//["B1", "b1"] ["B2", "b2"]

缺点:
父类被调用了两次,浪费
3.2.寄生组合继承(最优)

function createChild(obj){
var Child = function(){};
Child.prototype = obj;
return new Child();
}

function ClassA(){
this.id = [1];
}

ClassA.prototype.sayId = function(){
console.log(this.id);
}

function ClassB(){
ClassA.call(this);
}

var ClassC = createChild(ClassA.prototype);
ClassC.constructor = ClassB;
ClassB.prototype = ClassC;

var b1 = new ClassB();

参考文章:
JavaScript中的继承方式

此条目发表在JavaScript分类目录。将固定链接加入收藏夹。

发表评论

邮箱地址不会被公开。 必填项已用*标注